<template>
  <!--  file list  -->
  <el-upload
    v-if="listType === 'text' && !disabled"
    ref="upload"
    :disabled="disabled"
    :drag="drag"
    :show-file-list="false"
    :accept="accept"
    :multiple="multiple"
    :limit="maxLength"
    :before-upload="beforeUpload"
    :on-exceed="oneExceed"
    :http-request="customUpload"
    :on-error="onError"
  >
    <el-button type="primary" icon="Plus">上传</el-button>
    <template #tip>
      <div v-if="fileTip" class="el-upload__tip">{{ fileTip }}</div>
      <slot v-if="!fileTip && slots.customTip" name="customTip"></slot>
    </template>
  </el-upload>
  <div class="file-list" v-if="showFileList && listType === 'text'">
    <div class="file-list__item" v-for="(item, index) in fileListArr" :key="item.fileId">
      <div class="file-list__item-container">
        <div class="file-list__item-name one-ellipsis" @click="handelDownload(item)">{{ item.name }}</div>
        <div v-if="!disabled" class="file-list__item-del" @click="handelRemove(item, index)">x</div>
      </div>
      <el-progress
        v-if="ossStore.loadingArr[item.fileId] !== 100"
        :show-text="false"
        :percentage="ossStore.loadingArr[item.fileId]"
        :duration="10"
      />
    </div>
  </div>

  <!--  picture-card  -->
  <div class="picture-card" v-if="showFileList && listType === 'picture-card'">
    <div class="picture-card-list">
      <div class="picture-card__item" v-for="(item, index) in fileListArr" :key="item.fileId">
        <div class="picture-card__item-mask" v-if="!disabled">
          <el-icon @click="handelRemove(item, index)">
            <DeleteFilled />
          </el-icon>
        </div>
        <el-image
          :src="item.fileUrl"
          fit="cover"
          preview-teleported
          :preview-src-list="[item.fileUrl]"
          v-if="ossStore.loadingArr[item.fileId] === 100"
        ></el-image>
        <el-progress
          v-if="ossStore.loadingArr[item.fileId] !== 100"
          type="circle"
          striped
          striped-flow
          :percentage="ossStore.loadingArr[item.fileId]"
          :duration="10"
        />
      </div>
      <div class="picture-card__item" style="border: 0">
        <el-upload
          v-if="isShowUpload"
          ref="upload"
          :disabled="disabled"
          :drag="drag"
          :show-file-list="false"
          :accept="accept"
          :multiple="multiple"
          :limit="maxLength"
          :before-upload="beforeUpload"
          :on-exceed="oneExceed"
          :http-request="customUpload"
          :on-error="onError"
        >
          <div class="upload-picture-card">
            <el-icon>
              <Plus />
            </el-icon>
          </div>
          <!--            <template #tip>-->
          <!--              <div v-if="fileTip" class="el-upload__tip">{{ fileTip }}</div>-->
          <!--              <slot v-if="!fileTip && slots.customTip" name="customTip"></slot>-->
          <!--            </template>-->
        </el-upload>
      </div>
    </div>
  </div>
</template>

<script setup>
import { ref, computed, useSlots, watch } from "vue";
import { ElMessage } from "element-plus";
import { DeleteFilled, Plus } from "@element-plus/icons-vue";
import useMultipartOssStore from "@/store/modules/multipartOss";
import { setACL, signatureUrl } from "@/utils/aliOssUpload";
import defaultConfig from "@/settings";
import { generateId } from "@/utils/crm";

const slots = useSlots();
const ossStore = useMultipartOssStore();
const emits = defineEmits(["uploadSuccess", "onPreview", "removeFile"]);
const props = defineProps({
  folder: {
    type: String,
    default: ""
  },
  accept: {
    type: String,
    default: ""
  },
  showFileList: {
    type: Boolean,
    default: true
  },
  fileList: {
    type: Array,
    default: () => []
  },
  listType: {
    type: String,
    // default:"picture-card"
    default: "text"
  },
  maxSize: {
    type: Number,
    default: 9999999999
  },
  maxLength: {
    type: Number,
    default: 99999
  },
  fileTip: {
    type: String,
    default: ""
  },
  fileReadRole: {
    type: String,
    default: defaultConfig.fileReadRole.publicRead
  },
  disabled: Boolean,
  drag: Boolean,
  multiple: Boolean
});

const fileListArr = ref([]);

const isShowUpload = computed(() => {
  return !props.multiple && fileListArr.value.length ? false : true;
});

watch(
  () => props.fileList,
  newVal => {
    newVal.forEach(item => {
      ossStore.loadingArr[item.fileId] = 100;
    });
    console.log(newVal);
    fileListArr.value = [...newVal];
  }
);

const beforeUpload = file => {
  if (props.maxSize <= 0) {
    ElMessage.error(`请设置正确的文件大小！`);
    return false;
  }
  const maxSize = file.size / 1024 / 1024 < props.maxSize;
  if (!maxSize) {
    ElMessage.error(`上传文件大小不能超过${props.maxSize}M!`);
    return false;
  }
};

const oneExceed = files => {
  // console.log("oneExceed>>>",files)
  ElMessage.error(`最多上传${props.maxLength}个文件`);
  return false;
};

const getSuffix = fileName => {
  return fileName.slice(fileName.lastIndexOf(".") + 1);
};
const getFileName = fileName => {
  return fileName.slice(0, fileName.lastIndexOf("."));
};
const fileToBlob = file => {
  return {
    fileId: file.uid,
    uid: file.uid,
    name: file.name,
    size: file.size,
    type: file.type,
    suffix: file.suffix,
    fileUrl: URL.createObjectURL(file)
  };
};

const customUpload = async option => {
  fileListArr.value = [...fileListArr.value, fileToBlob(option.file)];
  ossStore.loadingArr[option.file.uid] = 0;
  let file = option.file,
    fileName = option.file.name;
  fileName = `${getFileName(fileName)}-${generateId()}.${getSuffix(fileName)}`;
  file = new File([file], fileName, { type: file.type });
  let objName = `${props.folder}/${file.name}`;
  ossStore
    .submit(objName, file, option.file.uid)
    .then(async res => {
      await setACL(objName, props.fileReadRole);
      if (props.fileReadRole === defaultConfig.fileReadRole.publicRead) {
        const fileUrl = await signatureUrl(objName);
        res.fileUrl = fileUrl ? `${fileUrl}`.split("?")[0] : "";
      }
      res.fileId = option.file.uid;
      res.size = file.size;
      res.file = option.file;
      res.fileName = file.name;
      res.file.suffix = getSuffix(file.name);
      emits("uploadSuccess", res);
    })
    .catch(err => {
      console.log(err);
      alert(JSON.stringify(err));
    });
};

const onError = err => {
  ElMessage.error(`文件上传失败：${JSON.stringify(err)}`);
};

const onPreview = async (file, index) => {
  const objName = `${props.folder}/${file?.name}`;
  emits("onPreview", { file, objName });
};

const handelDownload = item => {
  window.open(item.fileUrl);
};

const handelRemove = (file, index) => {
  fileListArr.value.splice(index, 1);
  file.index = index;
  emits("removeFile", file);
};
</script>

<style lang="scss" scoped>
$text-color-regular: #606266;
$picture-card-size: 84px;

@mixin flex-opt($justify-content: space-between, $align-items: center) {
  display: flex;
  display: -webkit-flex;
  justify-content: $justify-content;
  align-items: $align-items;
}

.one-ellipsis {
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.file-list {
  width: 100%;
  margin: 10px auto;

  &__item {
    cursor: pointer;
    margin-bottom: 5px;
    font-size: 14px;

    &-container {
      @include flex-opt;
      margin-bottom: 1px;
    }

    &-name {
      width: 95%;
      color: $text-color-regular;
    }

    &-del {
      display: inline-flex;
      display: -webkit-inline-flex;
      justify-content: center;
      align-items: center;
      width: 20px;
      height: 20px;
      border-radius: 50%;

      &:hover {
        background-color: rgba(0, 0, 0, 0.2);
      }
    }
  }
}

.picture-item {
  margin: 0 8px 8px 0;
  border: 1px solid #cdd0d6;
  cursor: pointer;
}

.upload-picture-card {
  @include flex-opt(center);
  width: $picture-card-size;
  height: $picture-card-size;
  border: 1px solid #cdd0d6;
  background-color: #fafafa;
  overflow: hidden;
  :deep(.el-icon) {
    font-size: 28px;
    color: #909399;
  }
}

.picture-card {
  display: flex;
  display: -webkit-flex;
  flex-wrap: wrap;
  width: 100%;
  .picture-card-list {
    width: 100%;
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax($picture-card-size, 1fr));
    grid-gap: 10px;
  }
  &__item {
    display: flex;
    display: -webkit-flex;
    align-items: center;
    position: relative;
    width: 100%;
    height: $picture-card-size;
    //border: 1px solid #cdd0d6;
    cursor: pointer;

    &:hover {
      .picture-card__item-mask {
        z-index: 999;
        background-color: rgba(0, 0, 0, 0.5);
      }
    }

    &-mask {
      @include flex-opt(center);
      position: absolute;
      width: 100%;
      height: 100%;
      z-index: -1;
      font-size: 20px;
      transition: background-color 0.3s;

      :deep(.el-icon) {
        color: #fff;

        & + .el-icon {
          margin-left: 10px;
        }
      }
    }

    :deep(.el-image) {
      width: 100%;
      height: 100%;
    }
  }
}

:deep(.el-upload__tip) {
  margin-top: 0;
  font-size: 12px;
  color: #86909c;
  line-height: 22px;
}
:deep(.el-progress-circle) {
  width: $picture-card-size !important;
  height: $picture-card-size !important;
}
</style>
